#include "RendererTypes.hpp"
#include "ListProxy.hpp"
#include "AxisAlignedBox.hpp"
#include "Vectors.hpp"
#include "ListProxy.hpp"

#include <list>

namespace cge {
	class Visible;

	class Octree {
	public:
		Octree( const AxisAlignedBox& bounds, unsigned maxDepth );
		Octree( Octree* parent, const AxisAlignedBox &box );
		~Octree();
	
		void     addVisible( Visible* visible );
		Octree*& getOctant(int x, int y, int z);
	
		bool     shouldPropagate( const vec3& size ) { return twiceSize_ >= size; }

		// inline getters
		ListProxy<VisibleList>  getChildren()       { return vis_;    }
		const AxisAlignedBox&   getBounds()   const { return bounds_; }

	private:
		Octree( Octree* parent );

		void    clearOctants_();
		void    addVisibleHere_( Visible *vis );
		void    removeVisible_ ( Visible *vis );
		void    updateBounds_() {
			twiceSize_ = bounds_.getSize()*2;
			center_    = bounds_.getCenter();
		}

		Octree*        parent_;
		Octree*        octants_[8];
		VisibleList    vis_;
		vec3           twiceSize_;
		vec3           center_;
		AxisAlignedBox bounds_;
		unsigned       maxDepth_;
	};
}